<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
	<link rel="stylesheet" href="/assets/css/atom-one-light.css">
    
        <title>用 D3.js 画一个 bubble chart</title>
		<link rel="stylesheet" type="text/css" href="/assets/css/002.css">
    
	<link rel="stylesheet" href="/assets/css/font-awesome.min.css">
	<link rel="shortcut icon" href="/assets/img/favicon.ico" type="image/x-icon">
	<link rel="icon" href="/assets/img/favicon.ico" type="image/x-icon">
	<script src="/assets/js/highlight.pack.js"></script>
	<script>hljs.initHighlightingOnLoad();</script>

	

	<script async src="https://www.googletagmanager.com/gtag/js?id=UA-140127665-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-140127665-1');
</script>


</head>
<body>
	<div class="wrapper">
		<div class="default_title">
			<img src="/assets/img/mycomputer.png" />
			
				<h1>NaNg's blog</h1>
			
		</div>
		<ul class="topbar">
	<a href="/pages/me.html"><li><u>A</u>bout</li></a>
	<a href="/pages/links.html"><li><u>L</u>inks</li></a>
	<a href="https://www.dropbox.com/sh/nhy3m3cvojizkk5/AABH8mt5gh3PiBrtWnCxE87ma?dl=0"><li><u>D</u>ropbox</li></a>
</ul>
		<div class="tag_list">
			<ul id="tag-list">
				<li><a href="/" ><img src="/assets/img/disk.png" />(C:)</a>
			<ul>
				
				
				<li><a href="/tag/3d/" title="3d"><img src="/assets/img/folder.ico" />3d</a></li>
				
				<li><a href="/tag/bioinformatics/" title="bioinformatics"><img src="/assets/img/folder.ico" />bioinformatics</a></li>
				
				<li><a href="/tag/notes/" title="notes"><img src="/assets/img/folder.ico" />notes</a></li>
				
				<li><a href="/tag/others/" title="others"><img src="/assets/img/folder.ico" />others</a></li>
				
				<li><a href="/tag/sci-fiction/" title="sci fiction"><img src="/assets/img/folder.ico" />sci fiction</a></li>
				
			</ul>
				</li>
			</ul>
		</div>
		<div class="post_list">
			
				<ul>
					
					<li>
						<a href="https://ani-net-project.gitee.io/index.html" title="AniNet">
								<img class="small-icon" src="/assets/img/aninet.png" title="AniNet" />AniNet
						</a>
					</li>
					
					<li>
						<a href="/examples/boids/index.html" title="Boids">
								<img class="small-icon" src="/assets/img/bird.png" title="Boids" />Boids
						</a>
					</li>
					
					<li>
						<a href="/examples/EM-alg/1_how_it_works.html" title="EM 算法 1. how it works">
								<img class="small-icon" src="/assets/img/notebook.ico" title="EM 算法 1. how it works" />EM 算法 1. how it works
						</a>
					</li>
					
					<li>
						<a href="/examples/pyvm/pyvm_ch0-3_cn.html" title="翻译：Inside Python Virtual Machine（前三章）">
								<img class="small-icon" src="/assets/img/html_ie.ico" title="翻译：Inside Python Virtual Machine（前三章）" />翻译：Inside Python Virtual Machine（前三章）
						</a>
					</li>
					
					<li>
						<a href="/20190624/cLife.html" title="器官工业幻想">
								<img class="small-icon" src="/assets/img/file.ico" title="器官工业幻想" />器官工业幻想
						</a>
					</li>
					
					<li>
						<a href="/examples/pubnet/Network_statistic.html" title="PubNet network statistic">
								<img class="small-icon" src="/assets/img/notebook.ico" title="PubNet network statistic" />PubNet network statistic
						</a>
					</li>
					
					<li>
						<a href="/examples/pubnet/sample.html" title="PubMed bio-conception network example">
								<img class="small-icon" src="/assets/img/net.png" title="PubMed bio-conception network example" />PubMed bio-conception network example
						</a>
					</li>
					
					<li>
						<a href="/examples/hpo_enrich/example_sagd_00055.html" title="HPO enrichment example">
								<img class="small-icon" src="/assets/img/notebook.ico" title="HPO enrichment example" />HPO enrichment example
						</a>
					</li>
					
					<li>
						<a href="/20190222/KS-Test.html" title="Two sample Kolmogorov-Smirnov test">
								<img class="small-icon" src="/assets/img/file.ico" title="Two sample Kolmogorov-Smirnov test" />Two sample Kolmogorov-Smirnov test
						</a>
					</li>
					
					<li>
						<a href="/20190220/threejs-test-page.html" title="three.js test page">
								<img class="small-icon" src="/assets/img/tree.png" title="three.js test page" />three.js test page
						</a>
					</li>
					
					<li>
						<a href="/20181111/hic_data_format.html" title="Hi-C 数据分析结果应该怎么存？">
								<img class="small-icon" src="/assets/img/file.ico" title="Hi-C 数据分析结果应该怎么存？" />Hi-C 数据分析结果应该怎么存？
						</a>
					</li>
					
					<li>
						<a href="/20181010/d3_bubble_chart.html" title="用 D3.js 画一个 bubble chart">
								<img class="small-icon" src="/assets/img/file.ico" title="用 D3.js 画一个 bubble chart" />用 D3.js 画一个 bubble chart
						</a>
					</li>
					
					<li>
						<a href="/20180724/new_kind_slides.html" title="论制作 Slides 的几种姿势">
								<img class="small-icon" src="/assets/img/file.ico" title="论制作 Slides 的几种姿势" />论制作 Slides 的几种姿势
						</a>
					</li>
					
					<li>
						<a href="/slides/test/slideshow.html" title="Markdown Slides Test">
								<img class="small-icon" src="/assets/img/slides.png" title="Markdown Slides Test" />Markdown Slides Test
						</a>
					</li>
					
					<li>
						<a href="/20180221/bioview.html" title="bioView - 一个生信常用文件格式的可读性增强工具">
								<img class="small-icon" src="/assets/img/file.ico" title="bioView - 一个生信常用文件格式的可读性增强工具" />bioView - 一个生信常用文件格式的可读性增强工具
						</a>
					</li>
					
					<li>
						<a href="/20170916/markdown-test-page.html" title="Markdown Test Page">
								<img class="small-icon" src="/assets/img/file.ico" title="Markdown Test Page" />Markdown Test Page
						</a>
					</li>
					
					<li>
						<a href="/20170831/gol-js.html" title="一个JS实现的生命游戏">
								<img class="small-icon" src="/assets/img/file.ico" title="一个JS实现的生命游戏" />一个JS实现的生命游戏
						</a>
					</li>
					
					<li>
						<a href="/20170831/parallel.html" title="这大概是程序串行改并行最简单粗暴的方法">
								<img class="small-icon" src="/assets/img/file.ico" title="这大概是程序串行改并行最简单粗暴的方法" />这大概是程序串行改并行最简单粗暴的方法
						</a>
					</li>
					
					<li>
						<a href="/20170730/learn-docker.html" title="学习Docker">
								<img class="small-icon" src="/assets/img/file.ico" title="学习Docker" />学习Docker
						</a>
					</li>
					
					<li>
						<a href="/20170530/learn-assemble.html" title="学习汇编语言">
								<img class="small-icon" src="/assets/img/file.ico" title="学习汇编语言" />学习汇编语言
						</a>
					</li>
					
					<li>
						<a href="/20170505/schoolnet.html" title="如何在非校园网环境下使用学校文献数据库">
								<img class="small-icon" src="/assets/img/file.ico" title="如何在非校园网环境下使用学校文献数据库" />如何在非校园网环境下使用学校文献数据库
						</a>
					</li>
					
					<li>
						<a href="/20170308/zerotier.html" title="使用ZeroTier搭建虚拟局域网">
								<img class="small-icon" src="/assets/img/file.ico" title="使用ZeroTier搭建虚拟局域网" />使用ZeroTier搭建虚拟局域网
						</a>
					</li>
					
					<li>
						<a href="/20161224/hy-in-brief.html" title="Python生态下的Lisp方言">
								<img class="small-icon" src="/assets/img/file.ico" title="Python生态下的Lisp方言" />Python生态下的Lisp方言
						</a>
					</li>
					
					<li>
						<a href="/20161210/scrapy_douban.html" title="使用Scrapy爬取豆瓣相册">
								<img class="small-icon" src="/assets/img/file.ico" title="使用Scrapy爬取豆瓣相册" />使用Scrapy爬取豆瓣相册
						</a>
					</li>
					
					<li>
						<a href="/20161115/speed_up_python.html" title="加速Python">
								<img class="small-icon" src="/assets/img/file.ico" title="加速Python" />加速Python
						</a>
					</li>
					
				</ul>
			
		</div>
		<div class="post_total">
			
				<div class="left">25 object(s)</div>
			
			<div class="right">&nbsp;</div>
		</div>
	</div>
	
        <div class="content">
			<div class="post_title">
				<img src="/assets/img/file.png" />
				<h1>用 D3.js 画一个 bubble chart</h1>
				<a href="/"><div class="btn"><span class="fa fa-times"></span></div></a>
				<div class="btn btn_max"><span class="fa fa-window-maximize"></span></div>
				<div class="btn"><span class="fa fa-window-minimize"></span></div>
			</div>
			<ul class="topbar">
				<li>October 10, 2018</li>
			</ul>
			<div class="post_content" style="max-height: 600px">
				<div class="post_content_inner">
        		<p>在展示 GO 富集分析的结果的时候经常会使用 bubble chart，
因为它的信息量相对来说比较大，bubble 的位置(x, y) ，大小和颜色，
每个属性都可以用来展示数据的某一维度信息。</p>

<!--more-->

<p>比方说，我可以这样建立数据到图形属性的映射关系：</p>
<pre><code>Gene ratio -&gt; x
GO item name -&gt; y
-log2(Pvalue) -&gt; size
mean log2(FoldChange) -&gt; color
</code></pre>

<p>可以通过这四个属性把我想展示的 GO 富集的结果信息都放在一张图上。</p>

<p>为了学习 D3.js 试用它来做了一个 bubble char。</p>

<p>做出来的效果是这样的：</p>

<html>
<script type="text/javascript" src="https://d3js.org/d3.v4.js"></script>
<style>
    #tooltip {
        position: absolute;
        width: auto;
        height: auto;
        padding: 10px;
        background-color: white;
        border-radius: 10px;
        box-shadow: 4px 4px 10px rgba(0,0,0,0.4);
        pointer-events: none;
    }

    #tooltip.hidden {
        display: none;
    }

    #tooltip p {
        margin: 0;
        font-family: sans-serif;
        font-size: 16px;
        line-height: 20px;
    }
</style>
        <div class="figure">
        <div id="tooltip" class="hidden">
            <div id="value"></div>
        </div>
        </div>
        <script type="text/javascript">

            var dataset = [{'term': 'defense response', 'log2Pvalue': 71.0437, 'GOType': 'P', 'count': 186, 'ratio': 0.20852, 'log2fc': 2.524810647917315}, {'term': 'immune system process', 'log2Pvalue': 65.414, 'GOType': 'P', 'count': 248, 'ratio': 0.278027, 'log2fc': 2.3277763018614333}, {'term': 'immune response', 'log2Pvalue': 64.6232, 'GOType': 'P', 'count': 186, 'ratio': 0.20852, 'log2fc': 2.519873045077976}, {'term': 'response to external stimulus', 'log2Pvalue': 56.6091, 'GOType': 'P', 'count': 210, 'ratio': 0.235426, 'log2fc': 2.416689680230685}, {'term': 'response to organic substance', 'log2Pvalue': 51.5985, 'GOType': 'P', 'count': 247, 'ratio': 0.276906, 'log2fc': 2.1673254588535165}, {'term': 'regulation of cell differentiation', 'log2Pvalue': 6.1193, 'GOType': 'P', 'count': 83, 'ratio': 0.106003, 'log2fc': -2.171376617354984}, {'term': 'cell proliferation', 'log2Pvalue': 5.80914, 'GOType': 'P', 'count': 103, 'ratio': 0.131545, 'log2fc': -2.218731079456651}, {'term': 'regulation of developmental process', 'log2Pvalue': 5.36019, 'GOType': 'P', 'count': 107, 'ratio': 0.136654, 'log2fc': -2.3008876543327164}, {'term': 'neural precursor cell proliferation', 'log2Pvalue': 5.29832, 'GOType': 'P', 'count': 13, 'ratio': 0.0166028, 'log2fc': -2.287330229906211}, {'term': 'negative regulation of developmental process', 'log2Pvalue': 4.42285, 'GOType': 'P', 'count': 41, 'ratio': 0.0523627, 'log2fc': -2.2817255999353763}]

            // (data) - (graphic element) mapping:
// 
//     gene ratio    ->> x pos
//     term name     ->> y pos
//     -log2(PValue) ->> circle size
//     log2(fc)      ->> circle color

// sort dataset by gene ratio
dataset = dataset.sort(function(a, b) {return a.ratio - b.ratio})

var dim = {
    w: 900,
    h: 600,
}

var margin = {
    top: 10,
    bottom: 50,
    left: 350,
    right: 200,
}

var padding = {
    top: 20,
    bottom: 20,
    left: 20,
    right: 20,
}

var w = dim.w - margin.left - margin.right,
    h = dim.h - margin.top - margin.bottom

var circleConfig = {
    size: {
        min:10,
        max:20
    },
    color: {
        min: "#66ccff",
        max: "#ff9c9c",
    },
    padding: h / dataset.length,
}

var svg = d3.select("div.figure")
            .append("svg")
            .attr("width", dim.w)
            .attr("height", dim.h)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")

var xScale = d3.scaleLinear()
    .domain([d3.min(dataset, function(d) {return d.ratio}),
             d3.max(dataset, function(d) {return d.ratio})])
    .range([padding.left, w-padding.right])

var yScale = d3.scaleBand()
    .domain(dataset.map(function(d) {return d.term}))
    .range([h-padding.bottom, padding.top])
    .paddingInner(circleConfig.padding)

var rScale = d3.scaleLinear()
    .domain([d3.min(dataset, function(d) {return d.log2Pvalue}),
             d3.max(dataset, function(d) {return d.log2Pvalue})])
    .range([circleConfig.size.min, circleConfig.size.max])

var log2fc_min = d3.min(dataset, function(d) {return d.log2fc}),
    log2fc_max = d3.max(dataset, function(d) {return d.log2fc})

var cScale = d3.scaleLinear()
    .domain([log2fc_min, log2fc_max])
    .interpolate(d3.interpolateHcl)
    .range([circleConfig.color.min, circleConfig.color.max])

var circles = svg.append("g")
    .attr("id", "circles")
    .selectAll("circle")
    .data(dataset)
    .enter()
    .append("circle")
    .attr("cx", function(d) {
        return xScale(d.ratio)
    })
    .attr("cy", function(d) {
        return yScale(d.term)
    })
    .attr("r", function(d) {
        return rScale(d.log2Pvalue)
    })
    .attr("fill", function(d) {
        return cScale(d.log2fc)
    })
    .attr("opacity", 0.8)


var formatPercent = d3.format(".0%");

var numXTicks = 5
var xAxis = d3.axisBottom()
    .scale(xScale)
    .ticks(numXTicks)
    .tickFormat(formatPercent)

var xTickFontSize = 18
svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + h + ")")
    .style("font-size", xTickFontSize)
    .call(xAxis)

var yAxis = d3.axisLeft()
    .scale(yScale)

var yTickFontSize = 15
svg.append("g")
    .attr("class", "y axis")
    .attr("transform", "translate(" + 0 + ", 0)")
    .style("font-size", yTickFontSize)
    .call(yAxis)

var xAxisLabelSize = 20
svg.append("text")
    .attr("class", "x axis lable")
    .attr("transform", "translate(" + w/2 + "," + (h + 40) + ")")
    .text("Gene Ratio")
    .style("font-size", xAxisLabelSize)
    .attr("text-anchor", "middle")

var numStop = 10
svg.append("defs")
    .append("linearGradient")
    .attr("id", "color-gradient")
    .attr("x1", "0%").attr("y1", "100%")
    .attr("x2", "0%").attr("y2", "0%")
    .selectAll("stop")
    .data(d3.range(numStop))
    .enter().append("stop")
    .attr("offset", function(d, i) {
        return i / (numStop - 1)
    })
    .attr("stop-color", function(d, i) {
        return cScale( log2fc_min + (log2fc_max - log2fc_min) * (i / (numStop - 1)) )
    })

var colorBarConfig = {
    height: 100,
    width: 30,
    pos: {
        x: w + 20,
        y: 0.7 * h,
    },
    title: {
        content: "Mean log2(FC)",
        fontSize: 16,
    },
    space: 5,
    ticks: {
        num: 3,
        fontSize: 14,
    }
}

svg.append("text")
    .text(colorBarConfig.title.content)
    .style("font-size", colorBarConfig.title.fontSize)
    .style("font-weight", "bold")
    .attr("transform", "translate(" + colorBarConfig.pos.x + "," +
                                      colorBarConfig.pos.y + ")")

svg.append("rect")
    .attr("width", colorBarConfig.width)
    .attr("height", colorBarConfig.height)
    .attr("transform", "translate(" + colorBarConfig.pos.x + "," +
                       (colorBarConfig.pos.y + colorBarConfig.space) + ")")
    .style("fill", "url(#color-gradient)")

var cbScale = d3.scaleLinear()
    .domain(cScale.domain())
    .range([colorBarConfig.height, 0])

var cAxis = d3.axisRight()
    .scale(cbScale)
    .ticks(colorBarConfig.ticks.num)

var cbTicks = svg.append("g")
    .attr("class", "c axis")
    .attr("transform", "translate(" + (colorBarConfig.pos.x + colorBarConfig.width) +
                       "," + (colorBarConfig.pos.y + colorBarConfig.space) + ")")
    .style("font-size", colorBarConfig.ticks.fontSize)
    .call(cAxis)

cbTicks.selectAll("path")
    .style("fill", "none")
    .style("stroke", "none")


sizeBarConfig = {
    num: 3,
    pos: {
        x: w + 20,
        y: h * 0.3,
    },
    title: {
        content: "-log2(pvalue)",
        fontSize: 16
    },
    space: 5,
    stops: {
        start: 0.25,
        end: 1,
    }
}

var sizeBarTitle = svg.append("text")
    .attr("class", "sizebar")
    .text(sizeBarConfig.title.content)
    .style("font-size", sizeBarConfig.title.fontSize)
    .style("font-weight", "bold")
    .attr("transform", "translate(" + sizeBarConfig.pos.x + "," +
                                      sizeBarConfig.pos.y + ")")

var getCircleExamples = function() {
    var ratio, size;
    var circleExamples = [],
        rs = sizeBarConfig.stops.start,
        re = sizeBarConfig.stops.end,
        smin = rScale.range()[0],
        smax = rScale.range()[1],
        logp_max = d3.max(dataset, function(d) {return d.log2Pvalue}),
        logp_min = d3.min(dataset, function(d) {return d.log2Pvalue})
    for (var i = 0; i < sizeBarConfig.num; i++) {
        ratio = rs + (re - rs) / (sizeBarConfig.num - 1) * i
        size = smin + (smax - smin) * ratio
        log2Pvalue = logp_min + (logp_max - logp_min) * ratio
        circleExamples.push({size: size, log2Pvalue: log2Pvalue})
    }
    return circleExamples
}

circleExamples = getCircleExamples()

var sizeBarCircles = svg.append("g")
    .attr("class", "sizebar")
    .attr("transform", "translate(" + sizeBarConfig.pos.x + "," +
                                      sizeBarConfig.pos.y + ")")
    .selectAll("circle")
    .data(circleExamples).enter()
    .append("circle")
    .attr("cx", function(d, i) {
        return rScale.range()[1]
    })
    .attr("cy", function(d, i) {
        return rScale.range()[1] + i * 2 * rScale.range()[1]
    })
    .attr("r", function(d, i) {
        return d.size
    })
    .attr("fill", "#555555")
    .attr("opacity", 0.8)

var sizeBarLabels = svg.append("g")
    .attr("class", "sizebar")
    .attr("transform", "translate(" + sizeBarConfig.pos.x + "," +
                                      sizeBarConfig.pos.y + ")")
    .selectAll("text")
    .data(circleExamples).enter()
    .append("text")
    .attr("x", function(d, i) {
        var rmax = rScale.range()[1]
        return 2 * rmax
    })
    .attr("y", function(d, i) {
        var rmax = rScale.range()[1]
        return rmax + i * 2 * rmax + 5
    })
    .text(function(d) {
        return d.log2Pvalue.toFixed(2)
    })

        </script>
</html>

<p>具体的代码放到了这个
<a href="https://github.com/Nanguage/D3-bubble-chart-example">repo</a> 里面，</p>

<p>D3.js 非常强大的绘图库，可以创建具有强动态效果的交互式
网页 SVG 图像。
交互式图像可以说是未来数据绘图的一种趋势，
而且用这种 html 模板渲染 D3.js 做图表的方式，
非常适合用来做生信软件或者 pipeline 的报告。
虽然现在也有一些其他语言的绘图库也可以做这类事情，
比如 Python 的 Plotly、Bokeh、Pygal 等等，
但总体来看，这些包还是不如 D3.js 强大、灵活。
所以 D3.js 还是非常值得研究一下的。</p>

				
					<br>
<hr>
<br>
<div class="donate">
	<p>Email: nanguage@yahoo.com</p>
</div>
				
				</div>
			</div>
		</div>
    
	<script src="/assets/js/001.js"></script>
	<script src="/assets/js/002.js"></script>
	<div class="footer">
		<p>blog theme: <a href="https://github.com/h01000110/windows-95">win95</a></p>
	</div>
</body>
</html>